package com.fzu.geometa.metadata.controller;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fzu.geometa.common.model.dto.RestResponse;
import com.fzu.geometa.metadata.eventdriven.publisher.MetadataEventPublisher;
import com.fzu.geometa.metadata.model.dto.ItemAddRequest;
import com.fzu.geometa.metadata.model.dto.ItemUpdateRequest;
import com.fzu.geometa.metadata.model.po.Item;
import com.fzu.geometa.metadata.service.*;
import com.fzu.geometa.metadata.util.JsonUtils;
import io.swagger.annotations.Api;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import static com.fzu.geometa.common.model.dto.RestResponse.success;
import static com.fzu.geometa.common.model.dto.RestResponse.validFail;

@RestController
@RequestMapping("/item")
@Api(tags = "Item")
public class ItemController {
    @Autowired
    private ItemService itemService;
    @Autowired
    private NamespaceService namespaceService;
    @Autowired
    private MetadataEventPublisher eventPublisher;

    @Autowired
    private ItemValidateService itemValidateService;

    @GetMapping(path = "/{eid}")
    public Item getItem(@PathVariable Long eid) {
        return itemService.getById(eid);
    }

    @PostMapping(path = "/update")
    public RestResponse updateItem(ItemUpdateRequest itemUpdateRequest) {
        if (itemUpdateRequest == null) {
            return validFail();
        }
        Item item = new Item();
        BeanUtils.copyProperties(itemUpdateRequest, item);
        // 后期添加统一的前后端数据格式
        // 更新必须有 eid
        if (item.getEid() == null) {
            return validFail();
        }
        // 数据校验
        if (validateItem(item) &&
                itemValidateService.updateWithValidation(item)) {
            // 缓存失效
            item = itemService.getById(item.getEid());
            // 更新检索
            eventPublisher.publishUpdateEvent(item.getCid());
            return success();
        } else {
            return validFail();
        }
    }

    @PostMapping(path = "/add")
    public RestResponse add(ItemAddRequest itemAddRequest) {
        if (itemAddRequest == null) {
            return validFail();
        }
        Item item = new Item();
        BeanUtils.copyProperties(itemAddRequest, item);

        if (validateItem(item) &&
                itemValidateService.addWithValidation(item)) {
            item = itemService.getById(item.getEid());
            // 更新检索
            eventPublisher.publishUpdateEvent(item.getCid());
            return success();
        } else {
            return validFail();
        }
    }

    @PostMapping(path = "/delete")
    public RestResponse delete(Long eid) {
        Item item = itemService.getById(eid);
        if (itemValidateService.deleteWithValidation(eid)) {
            // 更新检索
            eventPublisher.publishUpdateEvent(item.getCid());
            return success();
        } else {
            return validFail();
        }
    }

    // 校验 item
    private boolean validateItem(Item item) {
        // 检查name
        if (StringUtils.isBlank(item.getName())) {
            // name 不能为空
            return false;
        }
        // 检查namespace
        if (StringUtils.isBlank(item.getNamespace())) {
            item.setNamespace(null);
        }
        // 检查value
        if (StringUtils.isBlank(item.getValue())) {
            // 空白内容，置为空
            item.setValue(null);
        }
        // 检查 json
        if (StringUtils.isBlank(item.getAttributes())) {
            item.setAttributes(null);
        } else {
            // 检查 json 是否合法
            try {
                int hierarchyCount = JsonUtils.getHierarchyCount(item.getAttributes());
                if (hierarchyCount != 2) {
                    // 只能有一层字节点，总层数是2
                    return false;
                }
            } catch (JsonProcessingException e) {
                // 非法 json 字符串
                e.printStackTrace();
                return false;
            }
        }
        return true;
    }
}
